package com.bg.print.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bg.print.config.MinioConfig;
import com.bg.print.dao.FileDao;
import com.bg.print.dao.OrderDao;
import com.bg.print.dao.OrderDetailsDao;
import com.bg.print.dao.UserDao;
import com.bg.print.dto.OrderDetailsDto;
import com.bg.print.dto.OrderDto;
import com.bg.print.entity.FileEntity;
import com.bg.print.entity.OrderDetailsEntity;
import com.bg.print.entity.OrderEntity;
import com.bg.print.entity.UserEntity;
import com.bg.print.service.OrderService;
import com.bg.print.utils.Constant;
import com.bg.print.utils.PageUtils;
import com.bg.print.utils.Query;
import com.bg.print.utils.URLUtils;
import com.bg.print.variable.Enabled;
import com.bg.print.variable.OrderCancel;
import com.bg.print.variable.OrderStatus;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;


@Service("orderService")
public class OrderServiceImpl extends ServiceImpl<OrderDao, OrderEntity> implements OrderService {
    @Autowired
    private OrderDetailsDao orderDetailsDao;
    @Autowired
    private FileDao fileDao;
    @Autowired
    private UserDao userDao;
    @Autowired
    private MinioConfig minioConfig;
    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        LambdaQueryWrapper<OrderEntity> orderEntityWrapper = new LambdaQueryWrapper<>();
        if (params.get(Constant.USER_ID) != null)
            orderEntityWrapper.eq(OrderEntity::getUserId, params.get(Constant.USER_ID));
        if (params.get(Constant.STATUS) != null)
            orderEntityWrapper.eq(OrderEntity::getStatus, params.get(Constant.STATUS));
        if (params.get(Constant.ORDER_ID) != null)
            orderEntityWrapper.eq(OrderEntity::getUserId, params.get(Constant.ORDER_ID));
        return getOrderDtoPageUtils(params, orderEntityWrapper);
    }


    @Override
    @Transactional
    public OrderDto saveOrderDto(OrderDto order, UserDetails userDetails) {
        Date date = new Date();
        order.setUserId(getUser(userDetails).getId());
        order.setStatus(OrderStatus.SET_UP.getCode());
        order.setEnabled(Enabled.USING.getCode());
        order.setCancel(OrderCancel.ORDER_IN_PROGRESS.getCode());
        order.setCTime(date);
        this.baseMapper.insert(order);
        order.getOrderDetails().forEach(item -> {
            item.getFileEntity().setEnabled(Enabled.USING.getCode());
            item.getFileEntity().setModel(URLUtils.getPath(item.getFileEntity().getModel()));
            fileDao.insert(item.getFileEntity());
            item.setOrderId(order.getId());
            item.setEnabled(Enabled.USING.getCode());
            item.setFileId(item.getFileEntity().getId());
            orderDetailsDao.insert(item);
        });
        return order;
    }

    @Override
    public OrderDto getOrderDtoById(Long id) {
        OrderEntity orderEntity = this.baseMapper.selectById(id);
        if (orderEntity == null) return null;
        return getOrderDto(orderEntity);
    }


    /**
     * 查询自己的订单
     *
     * @param userDetails 用户
     * @param params      参数
     * @return 订单tdo
     */
    @Override
    public PageUtils getMyOrder(UserDetails userDetails, Map<String, Object> params) {
        LambdaQueryWrapper<OrderEntity> orderEntityWrapper = new LambdaQueryWrapper<>();
        orderEntityWrapper.eq(OrderEntity::getUserId, getUser(userDetails).getId());
        if (params.get(Constant.STATUS) != null)
            orderEntityWrapper.eq(OrderEntity::getStatus, params.get(Constant.STATUS));

        return getOrderDtoPageUtils(params, orderEntityWrapper);
    }


    /**
     * 删除
     *
     * @param list
     * @param userDetails
     */
    @Override
    @Transactional
    public Integer deleteByIds(List<Long> list, UserDetails userDetails) {
        LambdaQueryWrapper<OrderEntity> orderEntityLambdaQueryWrapper = new LambdaQueryWrapper<>();
        orderEntityLambdaQueryWrapper.eq(OrderEntity::getUserId, getUser(userDetails).getId());

        orderEntityLambdaQueryWrapper.in(OrderEntity::getId, list);
        return this.baseMapper.delete(orderEntityLambdaQueryWrapper);
    }


    /**
     * 返回报价
     *
     * @param id
     * @param money
     */
    @Transactional
    @Override
    public Integer oktMoney(Long id, BigDecimal money) {
        LambdaUpdateWrapper<OrderEntity> orderEntityLambdaQueryWrapper = new LambdaUpdateWrapper<>();
        orderEntityLambdaQueryWrapper.eq(OrderEntity::getId, id);
        orderEntityLambdaQueryWrapper.eq(OrderEntity::getStatus, OrderStatus.MAKE_OFFERS.getCode());
        orderEntityLambdaQueryWrapper.set(OrderEntity::getStatus, OrderStatus.QUOTATION_COMPLETED.getCode());
        orderEntityLambdaQueryWrapper.set(OrderEntity::getQuotation, money);
        return this.baseMapper.update(null, orderEntityLambdaQueryWrapper);
    }

    /**
     * 支付
     */
    @Transactional
    @Override
    public Integer buy(OrderEntity order, Long id, BigDecimal money) {
        LambdaUpdateWrapper<OrderEntity> orderEntityWrapper = new LambdaUpdateWrapper<>();
        orderEntityWrapper.eq(OrderEntity::getId, id);
        orderEntityWrapper.eq(OrderEntity::getStatus, OrderStatus.QUOTATION_COMPLETED.getCode());
        orderEntityWrapper.eq(OrderEntity::getQuotation, money);
        return this.baseMapper.update(order, orderEntityWrapper);
    }

    /**
     * 去打印订单
     *
     * @param id
     */
    @Transactional
    @Override
    public Integer toPrinting(Long id) {
        return updateStatus(id, null, List.of(OrderStatus.COMPLETE_PAYMENT.getCode()), null, OrderStatus.PRINTING.getCode());
    }

    /**
     * 完成打印
     *
     * @param id
     */
    @Transactional
    @Override
    public Integer okPrint(Long id) {
        return updateStatus(id, null, List.of(OrderStatus.PRINTING.getCode()), null, OrderStatus.PRINT_COMPLETE.getCode());
    }

    /**
     * 完成订单
     *
     * @param id
     * @param userDetails
     */
    @Override
    public Integer okOrder(Long id, UserDetails userDetails) {
        LambdaUpdateWrapper<OrderEntity> orderEntityWrapper = new LambdaUpdateWrapper<>();
        orderEntityWrapper.eq(OrderEntity::getUserId, getUser(userDetails).getId());
        orderEntityWrapper.eq(OrderEntity::getId, id);
        orderEntityWrapper.eq(OrderEntity::getStatus, OrderStatus.PRINT_COMPLETE.getCode());
        orderEntityWrapper.set(OrderEntity::getStatus, OrderStatus.ORDER_COMPLETION.getCode());
        orderEntityWrapper.set(OrderEntity::getDTime, new Date());
        return this.baseMapper.update(null, orderEntityWrapper);
    }

    /**
     * 申请报价
     */
    @Transactional
    @Override
    public Integer requestMoney(Long id, UserDetails userDetails) {
        return updateStatus(id, userDetails, List.of(OrderStatus.SET_UP.getCode()), null, OrderStatus.MAKE_OFFERS.getCode());
    }

    /**
     * 申请取消订单
     *
     * @param id
     * @param userDetails
     */
    @Override
    @Transactional
    public Integer qcancelOrder(Long id, UserDetails userDetails) {
        LambdaQueryWrapper<OrderEntity> orderEntityWrapper = new LambdaQueryWrapper<OrderEntity>();
        orderEntityWrapper.eq(OrderEntity::getId, id);
        orderEntityWrapper.eq(OrderEntity::getUserId, getUser(userDetails).getId());
        OrderEntity orderEntity = baseMapper.selectOne(orderEntityWrapper);
        if(Objects.equals(orderEntity.getCancel(), OrderCancel.REQUEST_ORDER_CANCELLATION.getCode())){
            return 0;
        }
        if(Objects.equals(orderEntity.getCancel(), OrderCancel.AGREE_TO_CANCEL_THE_ORDER.getCode())){
            return 0;
        }
        orderEntity.setCancel(OrderCancel.REQUEST_ORDER_CANCELLATION.getCode());
        return updateById(orderEntity)?1:0;
    }

    /**
     * 同意取消订单
     *
     * @param id
     * @return
     */
    @Override
    @Transactional
    public Integer okcancelOrder(Long id) {
        OrderEntity orderEntity = baseMapper.selectById(id);
        if(Objects.equals(orderEntity.getCancel(), OrderCancel.REQUEST_ORDER_CANCELLATION.getCode())){
            return 0;
        }
        if(Objects.equals(orderEntity.getCancel(), OrderCancel.AGREE_TO_CANCEL_THE_ORDER.getCode())){
            return 0;
        }
        orderEntity.setCancel(OrderCancel.REQUEST_ORDER_CANCELLATION.getCode());
        return updateById(orderEntity)?1:0;
    }

    /**
     * 驳回取消订单
     *
     * @param id
     * @return
     */
    @Override
    @Transactional
    public Integer nocancelOrder(Long id) {
        OrderEntity orderEntity = baseMapper.selectById(id);
        if(!Objects.equals(orderEntity.getCancel(), OrderCancel.REQUEST_ORDER_CANCELLATION.getCode())){
            return 0;
        }
        orderEntity.setCancel(OrderCancel.REJECTED_ORDER_CANCELLED.getCode());
        return updateById(orderEntity)?1:0;
    }

    /**
     * 放弃取消订单
     *
     * @param id
     * @return
     */
    @Override
    @Transactional
    public Integer cancelCancelOrder(Long id, UserDetails userDetails) {
        OrderEntity orderEntity = baseMapper.selectById(id);
        if(!Objects.equals(orderEntity.getCancel(), OrderCancel.REQUEST_ORDER_CANCELLATION.getCode())){
            return 0;
        }
        if(!Objects.equals(orderEntity.getUserId(), getUser(userDetails).getId())){
            return 0;
        }
        orderEntity.setCancel(OrderCancel.ORDER_IN_PROGRESS.getCode());
        return updateById(orderEntity)?1:0;
    }

    /**
     * 查询订单
     *
     * @param traceNo
     * @param id
     * @param totalAmount
     * @return
     */
    @Override
    public OrderEntity getByIdAndUser(String traceNo, UserDetails id, double totalAmount) {
        LambdaUpdateWrapper<OrderEntity> orderEntityWrapper = new LambdaUpdateWrapper<>();
        orderEntityWrapper.eq(OrderEntity::getUserId, getUser(id).getId());
        orderEntityWrapper.eq(OrderEntity::getId, traceNo);
        orderEntityWrapper.eq(OrderEntity::getStatus, OrderStatus.QUOTATION_COMPLETED.getCode());
        orderEntityWrapper.eq(OrderEntity::getQuotation, totalAmount);
        return this.baseMapper.selectOne(orderEntityWrapper);
    }

    @Override
    public OrderEntity getByTradeNo(String alipayTraceNo, String traceNo, double totalAmount) {
        LambdaQueryWrapper<OrderEntity> orderEntityWrapper = new LambdaQueryWrapper<>();
        orderEntityWrapper.eq(OrderEntity::getTradeNo, alipayTraceNo);
        orderEntityWrapper.eq(OrderEntity::getId, traceNo);
        orderEntityWrapper.eq(OrderEntity::getPayment, new BigDecimal(totalAmount));
        orderEntityWrapper.eq(OrderEntity::getCancel, OrderCancel.REQUEST_ORDER_CANCELLATION.getCode());
        return this.baseMapper.selectOne(orderEntityWrapper);
    }

    @Override
    public Integer nobuy(Long id) {
        LambdaUpdateWrapper<OrderEntity> orderEntityWrapper = new LambdaUpdateWrapper<>();
        orderEntityWrapper.eq(OrderEntity::getId, id);
        orderEntityWrapper.set(OrderEntity::getCancel, OrderCancel.AGREE_TO_CANCEL_THE_ORDER.getCode());
        orderEntityWrapper.set(OrderEntity::getDTime, new Date());
        return this.baseMapper.update(null, orderEntityWrapper);
    }

    /**
     * 通过订单查询tdo
     *
     * @param orderEntity
     * @return
     */
    public OrderDto getOrderDto(OrderEntity orderEntity) {
        OrderDto orderDto = new OrderDto();
        BeanUtils.copyProperties(orderEntity, orderDto);
        LambdaQueryWrapper<OrderDetailsEntity> orderDetailsEntityLambdaQueryWrapper = new LambdaQueryWrapper<>();
        orderDetailsEntityLambdaQueryWrapper.eq(OrderDetailsEntity::getOrderId, orderEntity.getId());
        List<OrderDetailsEntity> list = orderDetailsDao.selectList(orderDetailsEntityLambdaQueryWrapper);
        List<OrderDetailsDto> collect = list.stream().map(item -> {
            OrderDetailsDto orderDetailsDto = new OrderDetailsDto();
            BeanUtils.copyProperties(item, orderDetailsDto);
            FileEntity fileEntity = fileDao.selectById(item.getFileId());
            fileEntity.setModel(URLUtils.addPath(fileEntity.getModel(),minioConfig.getWarnEndpoint()));
            orderDetailsDto.setFileEntity(fileEntity);
            return orderDetailsDto;
        }).collect(Collectors.toList());
        orderDto.setOrderDetails(collect);
        return orderDto;
    }

    /**
     * 分页查询
     *
     * @param params
     * @param orderEntityWrapper
     * @return
     */
    private PageUtils getOrderDtoPageUtils(Map<String, Object> params, LambdaQueryWrapper<OrderEntity> orderEntityWrapper) {
        IPage<OrderEntity> page = this.page(
                new Query<OrderEntity>().getPage(params),
                orderEntityWrapper
        );
        List<OrderEntity> list = page.getRecords();
        List<OrderDto> orderDtoListDto = list.stream().map(this::getOrderDto).toList();
        PageUtils pageUtils = new PageUtils(page);
        pageUtils.setList(orderDtoListDto);
        return pageUtils;
    }

    /**
     * 更改订单状态
     *
     * @param id
     * @param userDetails
     * @param priors
     * @param noPrior
     * @param now
     * @return
     */
    @Transactional
    public Integer updateStatus(Long id, UserDetails userDetails, List<Integer> priors, List<Integer> noPrior, Integer now) {
        LambdaUpdateWrapper<OrderEntity> orderEntityWrapper = new LambdaUpdateWrapper<OrderEntity>();
        if (userDetails != null) {
            orderEntityWrapper.eq(OrderEntity::getUserId, getUser(userDetails).getId());
        }
        orderEntityWrapper.in(OrderEntity::getCancel,List.of(OrderCancel.ORDER_IN_PROGRESS.getCode(),OrderCancel.REJECTED_ORDER_CANCELLED.getCode()) );//正在进行
        orderEntityWrapper.eq(OrderEntity::getId, id);
        if (priors != null && !priors.isEmpty())
            orderEntityWrapper.in(OrderEntity::getStatus, priors);
        if (noPrior != null && !noPrior.isEmpty())
            orderEntityWrapper.notIn(OrderEntity::getStatus, noPrior);
        orderEntityWrapper.set(OrderEntity::getStatus, now);
        return this.baseMapper.update(null, orderEntityWrapper);
    }

    @Transactional
    public Integer updateCancel(Long id, UserDetails userDetails, List<Integer> priors, List<Integer> noPrior, Integer now) {
        LambdaUpdateWrapper<OrderEntity> orderEntityWrapper = new LambdaUpdateWrapper<OrderEntity>();
        if (userDetails != null) {
            orderEntityWrapper.eq(OrderEntity::getUserId, getUser(userDetails).getId());
        }
        orderEntityWrapper.eq(OrderEntity::getId, id);
        if (priors != null && !priors.isEmpty())
            orderEntityWrapper.in(OrderEntity::getCancel, priors);
        if (noPrior != null && !noPrior.isEmpty())
            orderEntityWrapper.notIn(OrderEntity::getCancel, noPrior);
        orderEntityWrapper.set(OrderEntity::getCancel, now);
        return this.baseMapper.update(null, orderEntityWrapper);
    }

    /**
     * 获取用户
     *
     * @param userDetails
     * @return
     */
    public UserEntity getUser(UserDetails userDetails) {
        LambdaQueryWrapper<UserEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserEntity::getAccount, userDetails.getUsername());
        return userDao.selectOne(queryWrapper);
    }

}